package com.teamwin.hdmi;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.os.Bundle;
import android.view.Display;
import android.view.WindowManager;

public class SocketManager extends Activity {
	private boolean autoRotate = false;
	private boolean bannersEnabled = true;
	private boolean commandHasResult;
	private boolean manualResolution = false;
	private boolean mirroring = false;
	private boolean vSync = true;
	
	public static final int	ROTATE_NONE = 0;
	public static final int	ROTATE_90 = 1;
	public static final int	ROTATE_180 = 2;
	public static final int	ROTATE_270 = 3;
	public static final int	ENABLE = 4;
	public static final int	DISABLE = 5;
	public static final int	SCALE_FIT_TO_SCREEN = 6;
	public static final int	SCALE_CENTER = 7;
	public static final int	SCALE_STRETCH = 8;
	public static final int	GET_RESOLUTIONS_SUPPORTED = 9;
	public static final int	GET_CABLE_STATUS = 10;
	public static final int	GET_MIRROR_STATUS = 11;
	public static final int	SET_RESOLUTION = 12;
	public static final int SET_BANNER = 13;
	public static final int SET_OVERSCAN = 14;
	public static final int SET_SCALING = 15;
	public static final int SET_VSYNC = 16;
	public static final int GET_KERNEL_STATUS = 17;
	public static final int GET_DAEMON_VERSION = 18;
	public static final int DAEMON_QUIT = 19;
	
	public static final int NEW_DAEMON = 20;
	public static final int NEED_KERNEL = 21;
	public static final int CHECK_VERSION = 22;
	
	private int selectedResolution = 0;
	private int port = 61083;
	
	private SharedPreferences settings = null;
	private SharedPreferences.Editor editor = null;
	
	private Socket socket;
	
	private String chosenRez;
	private String commandResult;
	private String currentResolution;
	private String orientation;
	private int scaling;
	
	public static final String APP_SETTINGS = "hdmwin";
	private final static String STATE_FILE = "/data/hdmid/state";
//	private static final String CUSTOM_INTENT = "com.teamwin.hdmi.INSTALLER";
	protected final static String versionUrl = "http://www.techerrata.com/version.php?app=hdmi";
	
	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
				
		this.settings = getSharedPreferences(APP_SETTINGS, 0);
		this.editor = settings.edit();
		
//		System.out.println("KERNEL INSTALLED: " + settings.getBoolean("kernel_installed", false));
		
		setContentView(R.layout.main);

		this.setMirroring(this.sendCommand(GET_MIRROR_STATUS, null).equalsIgnoreCase("1"));
		this.setAutoRotate(this.getSettings().getBoolean("auto_rotate", false));
		this.setOrientation(this.getSettings().getString("orientation", ""));
		
		this.setBannersEnabled(this.getSettings().getBoolean("banners_enabled", true));
		this.setManualResolution(this.getSettings().getBoolean("manual_resolution", false));
		
		chosenRez = settings.getString("resolution", "");
	}
	
	protected void onResume() {
		this.settings = getSharedPreferences(SocketManager.APP_SETTINGS, 0);
		this.editor = settings.edit();
		
		boolean bEnabled = settings.getBoolean("banners_enabled", true);
		this.setBannersEnabled(bEnabled);
		
		boolean manResEnabled = settings.getBoolean("manual_resolution", false);
		this.setManualResolution(manResEnabled);
		
//		this.checkSocket();
		this.setMirroring(this.sendCommand(GET_MIRROR_STATUS, null).equalsIgnoreCase("1"));
		this.setAutoRotate(this.getSettings().getBoolean("auto_rotate", false));
		this.setOrientation(this.getSettings().getString("orientation", ""));
		super.onResume();
	}
	
	protected void onPause() {
		try {
			if (this.socket != null && this.socket.isConnected()) {
				this.socket.close();
			}
			this.socket = null;
		} catch (IOException e) {
			e.printStackTrace();
		}
        
        super.onPause();
	}
	
	@Override
	public void onConfigurationChanged(Configuration newConfig) {
		if (this.isAutoRotate()) {
			int r = (getResources().getConfiguration().orientation);
			if (r == Configuration.ORIENTATION_LANDSCAPE || r == Configuration.ORIENTATION_PORTRAIT) {
				Display display = ((WindowManager) getSystemService(Context.WINDOW_SERVICE))
						.getDefaultDisplay();
				int rotation = display.getRotation();
				this.sendCommand(rotation, null);
			}
		}
		super.onConfigurationChanged(newConfig);
	}
	
	public void checkPort() {
		File file = new File(STATE_FILE);
		if (file.exists()) {
			BufferedReader br;
			try {
				br = new BufferedReader(new FileReader(file));
				String line = null;
				while ((line = br.readLine()) != null) {
					if (line.contains("port")) {
						this.setPort(Integer.parseInt(line.substring(line.indexOf("=") + 1, line.lastIndexOf(";"))));
						System.out.println("Found the port! " + port);
					}
				}
			} catch (FileNotFoundException e1) {
				e1.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
	public void startInstaller(int reason, int latestVersion) {
		Intent intent = new Intent(this, Installer.class);
		intent.putExtra("installer_reason", reason);
		if (latestVersion != -1) {
			intent.putExtra("latest_version", latestVersion);
		}
		startActivity(intent);
	}
	
	public void checkSocket() {
		if (this.getSocket() == null || !this.getSocket().isConnected()) {
			try {
				this.checkPort();
				this.setSocket(new Socket("127.0.0.1", port));
				this.getSocket().setKeepAlive(true);
			} catch (UnknownHostException e) {
				e.printStackTrace();
			} catch (IOException e) {
				Process p = null;
				try {
					p = Runtime.getRuntime().exec("su");
					DataOutputStream dos = new DataOutputStream(p.getOutputStream());
					dos.write("hdmid &\n".getBytes());
					dos.flush();
					dos.close();
					// mount command: mount -o remount,rw /dev/block/mtdblock4 /system
				} catch (IOException ex) {
					ex.printStackTrace();
				}
			}
		}
	}

	public boolean hasAcceleratedKernel() {
//		return true;
		return this.sendCommand(GET_KERNEL_STATUS, null).equalsIgnoreCase("1");
//		return !this.getSettings().getBoolean("kernel_installed", false);
	}
	
	public String sendCommand(int command, String optional) {
		String rval = "0";
		String toSend = null;
		
		switch (command) {
			case ENABLE:
				toSend = "e";
				if (!this.isvSync()) {
					toSend += "|v3";
				}
				if (!this.isBannersEnabled()) {
					toSend += "|a0";
				}
				break;
			case DISABLE:
				toSend = "d";
				break;
			case ROTATE_NONE:
				toSend = "r0";
				break;
			case ROTATE_90:
				toSend = "r1";
				break;
			case ROTATE_180:
				toSend = "r2";
				break;
			case ROTATE_270:
				toSend = "r3";
				break;
			case GET_RESOLUTIONS_SUPPORTED:
				if (useManualResolution()) {
					return "11280x720,800x600,720x576,720x480,640x480,0x0";
				}
				toSend = "l";
				break;
			case GET_CABLE_STATUS:
				toSend = "c";
				break;
			case GET_MIRROR_STATUS:
				toSend = "m";
				break;
			case GET_KERNEL_STATUS:
				toSend = "k";
				break;
			case SET_RESOLUTION:
				toSend = "x";
				if (optional != null) {
					toSend += optional + "x16";
				}
				break;
			case SET_BANNER:
				toSend = "a";
				toSend += (optional != null ? optional : "default");
				// white = ((255 * 256 * 256) + (255 * 256) + 255);
				break;
			case SET_OVERSCAN:
				toSend = "o";
				toSend += (optional != null ? optional : "0");
				break;
			case SET_SCALING:
				toSend = "s";
				toSend += (optional != null ? optional : "0");
				break;
			case SCALE_CENTER:
				toSend = "s1";
				break;
			case SCALE_STRETCH:
				toSend = "s2";
				break;
			case SET_VSYNC:
				toSend = "v";
				toSend += (optional != null ? 
						(optional.equalsIgnoreCase("1") ? "2" : "3") 
						: "2");
				break;
			case GET_DAEMON_VERSION:
				toSend = "n";
				break;
			case DAEMON_QUIT:
				toSend = "q";
				break;
			default:
				break;
		}
		
		this.checkSocket();
		try {
			if (this.socket != null) {
				if (!toSend.equalsIgnoreCase("q")) {
					SocketListenerThread thread = new SocketListenerThread(this);
					thread.start();
				}
				DataOutputStream os = new DataOutputStream(socket.getOutputStream());
//				System.out.println("SocketManager::sendCommand() - sending command:" + toSend + "\n");
				os.writeBytes(toSend + "\n");
				os.flush();
				if (!toSend.equalsIgnoreCase("q")) {
					while (!this.hasCommandResult()) {
						// wait
					}
					this.setHasCommandResult(false);
					rval = this.getCommandResult();
//					System.out.println("SocketManager::sendCommand() - received response: " + this.getCommandResult());
					this.setCommandResult("0");
				} else {
					os.close();
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		return rval;
	}
	
	public void setBannersEnabled(boolean bannersEnabled) {
		this.bannersEnabled = bannersEnabled;
	}

	public boolean isBannersEnabled() {
		return bannersEnabled;
	}
	
	public boolean useManualResolution() {
		return manualResolution;
	}
	
	public void setHasCommandResult(boolean hasResult) {
		this.commandHasResult = hasResult;
	}

	public boolean hasCommandResult() {
		return commandHasResult;
	}

	public void setCommandResult(String commandResult) {
		this.commandResult = commandResult;
	}

	public String getCommandResult() {
		return commandResult;
	}

	
	public SharedPreferences getSettings() {
		return settings;
	}

	public void setSettings(SharedPreferences settings) {
		this.settings = settings;
	}

	public SharedPreferences.Editor getEditor() {
		return editor;
	}

	public void setEditor(SharedPreferences.Editor editor) {
		this.editor = editor;
	}

	public Socket getSocket() {
		return socket;
	}

	public void setSocket(Socket socket) {
		this.socket = socket;
	}

	public boolean isCommandHasResult() {
		return commandHasResult;
	}

	public void setCommandHasResult(boolean commandHasResult) {
		this.commandHasResult = commandHasResult;
	}

	public String getChosenRez() {
		return chosenRez;
	}

	public void setChosenRez(String chosenRez) {
		this.chosenRez = chosenRez;
	}

	public String getCurrentResolution() {
		return currentResolution;
	}

	public void setCurrentResolution(String currentResolution) {
		this.currentResolution = currentResolution;
	}

	public void setManualResolution(boolean manualResolution) {
		this.manualResolution = manualResolution;
		this.editor.putBoolean("manual_resolution", manualResolution);
		this.editor.commit();
	}

	public boolean isAutoRotate() {
		return autoRotate;
	}

	public void setAutoRotate(boolean autoRotate) {
		this.autoRotate = autoRotate;
	}

	public boolean isMirroring() {
		return mirroring;
	}

	public void setMirroring(boolean mirroring) {
		this.mirroring = mirroring;
	}

	public String getOrientation() {
		return orientation;
	}

	public void setOrientation(String orientation) {
		this.orientation = orientation;
	}

	public int getScaling() {
		return scaling;
	}

	public void setScaling(int scaling) {
		this.scaling = scaling;
	}

	public void setSelectedResolution(int selectedResolution) {
		this.selectedResolution = selectedResolution;
	}

	public int getSelectedResolution() {
		return selectedResolution;
	}

	public boolean isvSync() {
		return vSync;
	}

	public void setvSync(boolean vSync) {
		this.vSync = vSync;
	}

	public int getPort() {
		return port;
	}

	public void setPort(int port) {
		this.port = port;
	}
}
